﻿using System.Collections.Generic;
using System;
using System.Web.Script.Serialization;
using Taype.Trading.BTC.Utilities;

namespace Taype.Trading.BTC.MtGoxAPIClient.JSONObjects
{
    /// <summary>
    /// Encapsulates an item in an account history dump returned by the info() method
    /// </summary>
    public class MtGoxHistoryItem
    {

        public string Login { get; set; }

        public int Index { get; set; }

        public List<string> Rights { get; set; }

        public string Language { get; set; }

        public DateTime Created { get; set; }

        public DateTime Last_Login { get; set; }

        public List<MtGoxWallet> Wallets { get; set; }

        public double Trade_Fee { get; set; }

        public MtGoxHistoryItem()
        { }
        
        /// <summary>
        /// Parse the JSON data returned by the 0/info.php method
        /// </summary>
        /// <param name="jsonDataStr">JSON data returned by the 0/info.php method</param>
        /// <returns></returns>
        public static MtGoxHistoryItem getObjects(string jsonDataStr)
        {
            // jsonDataStr will look as follows: "{\"Login\":\"taype-autotrader\",\"Index\":\"110333\",\"Rights\":[\"deposit\",\"get_info\",\"trade\",\"withdraw\"],\"Language\":\"en_US\",\"Created\":\"2012-01-02 20:51:43\",\"Last_Login\":\"2012-01-06 20:00:15\",\"Wallets\":{\"BTC\":{\"Balance\":{\"value\":\"0.86053625\",\"value_int\":\"86053625\",\"display\":\"0.86053625\\u00a0BTC\",\"currency\":\"BTC\"},\"Operations\":1,\"Daily_Withdraw_Limit\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"},\"Monthly_Withdraw_Limit\":null,\"Max_Withdraw\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"}},\"USD\":{\"Balance\":{\"value\":\"0.00000\",\"value_int\":\"0\",\"display\":\"$0.00000\",\"currency\":\"USD\"},\"Operations\":0,\"Daily_Withdraw_Limit\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"},\"Monthly_Withdraw_Limit\":{\"value\":\"10000.00000\",\"value_int\":\"1000000000\",\"display\":\"$10,000.00000\",\"currency\":\"USD\"},\"Max_Withdraw\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"}}},\"Trade_Fee\":0.6}"
            string json = jsonDataStr;
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
            dynamic obj = serializer.Deserialize(json, typeof(object));
            MtGoxHistoryItem hi = new MtGoxHistoryItem();
            // "{\"Login\":\"taype-autotrader\",
            hi.Login = obj.Login.ToString();
            // \"Index\":\"110333\",
            hi.Index = int.Parse(obj.Index.ToString());
            // \"Rights\":[\"deposit\",\"get_info\",\"trade\",\"withdraw\"],
            hi.Rights = new List<string>();
            for (int i = 0; i < obj.Rights.Count; i++)
            {
                hi.Rights.Add(obj.Rights[i].ToString());
            }
            // \"Language\":\"en_US\",
            hi.Language = obj.Language.ToString();
            // \"Created\":\"2012-01-02 20:51:43\",
            hi.Created = DateTime.Parse(obj.Created.ToString());
            // \"Last_Login\":\"2012-01-06 20:00:15\",
            hi.Last_Login = DateTime.Parse(obj.Last_Login.ToString());
            // \"Wallets\":{\"BTC\":{\"Balance\":{\"value\":\"0.86053625\",\"value_int\":\"86053625\",\"display\":\"0.86053625\\u00a0BTC\",\"currency\":\"BTC\"},\"Operations\":1,\"Daily_Withdraw_Limit\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"},\"Monthly_Withdraw_Limit\":null,\"Max_Withdraw\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"}},\"USD\":{\"Balance\":{\"value\":\"0.00000\",\"value_int\":\"0\",\"display\":\"$0.00000\",\"currency\":\"USD\"},\"Operations\":0,\"Daily_Withdraw_Limit\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"},\"Monthly_Withdraw_Limit\":{\"value\":\"10000.00000\",\"value_int\":\"1000000000\",\"display\":\"$10,000.00000\",\"currency\":\"USD\"},\"Max_Withdraw\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"}}},
            hi.Wallets = new List<MtGoxWallet>();
            // iterate through each currency to see if a wallet exists
            // for now I can't think of a way to do this programatically, just make sure that whenever a new currency is added
            // to the MtGoxCurrencySymbol enum that this method is updated accordingly
            // USD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("USD", obj.Wallets.USD));
            }
            catch(Exception ex) 
            { }
            // AUD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("AUD", obj.Wallets.AUD));
            }
            catch (Exception ex)
            { }
            // CAD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("CAD", obj.Wallets.CAD));
            }
            catch (Exception ex)
            { }
            // CHF
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("CHF", obj.Wallets.CHF));
            }
            catch (Exception ex)
            { }
            // CNY
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("CNY", obj.Wallets.CNY));
            }
            catch (Exception ex)
            { }
            // DKK
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("DKK", obj.Wallets.DKK));
            }
            catch (Exception ex)
            { }
            // EUR
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("EUR", obj.Wallets.EUR));
            }
            catch (Exception ex)
            { }
            // GBP
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("GBP", obj.Wallets.GBP));
            }
            catch (Exception ex)
            { }
            // HKD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("HKD", obj.Wallets.HKD));
            }
            catch (Exception ex)
            { }
            // JPY
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("JPY", obj.Wallets.JPY));
            }
            catch (Exception ex)
            { }
            // NZD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("NZD", obj.Wallets.NZD));
            }
            catch (Exception ex)
            { }
            // PLN
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("PLN", obj.Wallets.PLN));
            }
            catch (Exception ex)
            { }
            // RUB
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("RUB", obj.Wallets.RUB));
            }
            catch (Exception ex)
            { }
            // SEK
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("SEK", obj.Wallets.SEK));
            }
            catch (Exception ex)
            { }
            // SGD
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("SGD", obj.Wallets.SGD));
            }
            catch (Exception ex)
            { }
            // THB
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("THB", obj.Wallets.THB));
            }
            catch (Exception ex)
            { }
            // BTC
            try
            {
                hi.Wallets.Add(MtGoxHistoryItem.BuildWallet("BTC", obj.Wallets.BTC));
            }
            catch (Exception ex)
            { }
            // \"Trade_Fee\":0.6}"
            hi.Trade_Fee = double.Parse(obj.Trade_Fee.ToString());
            return hi;
        }

        /// <summary>
        /// Helper method to build wallet objects
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static MtGoxWallet BuildWallet(string walletName, dynamic obj)
        {
            if(obj == null)
                throw new Exception("No wallet for this currency");
            // first extract wallet name
            MtGoxCurrencySymbol name = (MtGoxCurrencySymbol)Enum.Parse(typeof(MtGoxCurrencySymbol), walletName, true);
            // now extract balance info
            MtGoxWalletBalance bal = new MtGoxWalletBalance(double.Parse(obj.Balance.value), Int64.Parse(obj.Balance.value_int), obj.Balance.display, (MtGoxCurrencySymbol)Enum.Parse(typeof(MtGoxCurrencySymbol), obj.Balance.currency, true));
            // now operations
            int ops = obj.Operations;
            // now daily withdrawal limit
            MtGoxWithdrawalLimit dwd = null;
            if (obj.Daily_Withdraw_Limit != null)
            {
                dwd = new MtGoxWithdrawalLimit(double.Parse(obj.Daily_Withdraw_Limit.value), Int64.Parse(obj.Daily_Withdraw_Limit.value_int), obj.Daily_Withdraw_Limit.display, (MtGoxCurrencySymbol)Enum.Parse(typeof(MtGoxCurrencySymbol), obj.Daily_Withdraw_Limit.currency, true));
            }
            // now monthly withdrawal limit
            MtGoxWithdrawalLimit mwd = null;
            if (obj.Monthly_Withdraw_Limit != null)
            {
                mwd = new MtGoxWithdrawalLimit(double.Parse(obj.Monthly_Withdraw_Limit.value), Int64.Parse(obj.Monthly_Withdraw_Limit.value_int), obj.Monthly_Withdraw_Limit.display, (MtGoxCurrencySymbol)Enum.Parse(typeof(MtGoxCurrencySymbol), obj.Monthly_Withdraw_Limit.currency, true));
            }
            // now max withdrawal limit
            MtGoxWithdrawalLimit maxwd = null;
            if (obj.Max_Withdraw != null)
            {
                maxwd = new MtGoxWithdrawalLimit(double.Parse(obj.Max_Withdraw.value), Int64.Parse(obj.Max_Withdraw.value_int), obj.Max_Withdraw.display, (MtGoxCurrencySymbol)Enum.Parse(typeof(MtGoxCurrencySymbol), obj.Max_Withdraw.currency, true));
            }
            MtGoxWallet wal = new MtGoxWallet(name, bal, ops, dwd, mwd, maxwd);
            return wal;
        }
    }
}
